<!-- 消息通知 -->
<template>
  <div class="message-notifications">
    <!-- 筛选区域 -->
    <div class="controls-section">
      <div class="filters">
        <div class="filter-item">
          <label>关键词</label>
          <input v-model.trim="query.keyword" type="text" placeholder="请输入关键词">
        </div>
        <div class="filter-item">
          <label>状态</label>
          <select v-model="query.status">
            <option :value="''">请选择</option>
            <option :value="'UNREAD'">未读</option>
            <option :value="'READ'">已读</option>
          </select>
        </div>
      </div>
      <div class="actions">
        <button class="btn-primary" @click="onSearch">搜索</button>
        <button class="btn-secondary" @click="onReset">重置</button>
        <button class="btn-success" @click="showCreateForm">创建通知</button>
        <span class="unread-badge" v-if="stats.unread != null">未读：{{ stats.unread }}</span>
      </div>
    </div>

    <!-- 标签页 -->
    <div class="tabs">
      <button :class="['tab', activeTab==='all'?'active':'']" @click="switchTab('all')">全部消息</button>
      <button :class="['tab', activeTab==='mine'?'active':'']" @click="switchTab('mine')">@ 我的</button>
      <button :class="['tab', activeTab==='system'?'active':'']" @click="switchTab('system')">系统消息</button>
      <button :class="['tab', activeTab==='company'?'active':'']" @click="switchTab('company')">公司消息</button>
      <button :class="['tab', activeTab==='product'?'active':'']" @click="switchTab('product')">产品消息</button>
    </div>

    <!-- 表格区域 -->
    <div class="table-section">
      <table>
        <thead>
          <tr>
            <th>通知标题</th>
            <th>状态</th>
            <th>类型</th>
            <th>发布时间</th>
            <th style="width:140px;">操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="row in list" :key="row.id">
            <td class="link-style" @click="viewDetail(row)">{{ row.title }}</td>
            <td :class="{ 'status-unread': row.readStatus!=='READ', 'status-read': row.readStatus==='READ' }">{{ row.readStatus==='READ' ? '已读' : '未读' }}</td>
            <td>{{ row.type || '-' }}</td>
            <td>{{ formatTime(row.publishedAt || row.createTime) }}</td>
            <td>
              <button class="btn-secondary btn-xs" @click="viewDetail(row)">查看</button>
              <button class="btn-danger btn-xs" @click="remove(row)">删除</button>
            </td>
          </tr>
          <tr v-if="list.length===0">
            <td colspan="5" style="text-align:center;color:#909399;padding:16px;">暂无数据</td>
          </tr>
        </tbody>
      </table>
    </div>

    <!-- 分页 -->
    <div class="pagination">
      <button @click="prevPage" :disabled="page.pageNum===1">&lt;</button>
      <button v-for="pageNo in totalPages" :key="pageNo" :class="{ active: page.pageNum === pageNo }" @click="goToPage(pageNo)">{{ pageNo }}</button>
      <button @click="nextPage" :disabled="page.pageNum===totalPages">&gt;</button>
      <select v-model.number="page.pageSize" @change="onSizeChange">
        <option :value="10">10条/页</option>
        <option :value="20">20条/页</option>
        <option :value="50">50条/页</option>
      </select>
    </div>

    <!-- 创建通知弹窗 -->
    <div v-if="createVisible" class="modal-overlay" @click.self="closeCreateForm">
      <div class="modal" style="width: min(900px, 95vw);">
        <div class="modal-header">
          <div class="modal-title">创建消息通知</div>
          <button class="modal-close" @click="closeCreateForm">×</button>
        </div>
        <div class="modal-body">
          <CreateNotification @success="onCreateSuccess" @cancel="closeCreateForm" />
        </div>
      </div>
    </div>

    <!-- 详情弹窗 -->
    <div v-if="detailVisible" class="modal-overlay" @click.self="closeDetail">
      <div class="modal">
        <div class="modal-header">
          <div class="modal-title">{{ detail.title || '通知详情' }}</div>
          <button class="modal-close" @click="closeDetail">×</button>
        </div>
        <div class="modal-body">
          <div class="meta">
            <span>类型：{{ detail.type || '-' }}</span>
            <span>发布时间：{{ formatTime(detail.publishedAt) }}</span>
          </div>
          <div v-if="detailLoading" class="loading">加载中...</div>
          <div v-else class="detail-content" v-html="detail.content || '<div style=\'color:#909399\'>暂无内容</div>'"></div>
        </div>
        <div class="modal-footer">
          <button class="btn-secondary" @click="closeDetail">关闭</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { getUserNotices, getNoticeStats, markAsRead, deleteNotice, connectNoticeStream, getNoticeDetail } from '@/api/notice'
import CreateNotification from './CreateNotification.vue'

export default {
  name: 'MessageNotifications',
  components: {
    CreateNotification
  },
  data() {
    return {
      activeTab: 'all',
      query: { keyword: '', status: '' },
      page: { pageNum: 1, pageSize: 10, total: 0 },
      list: [],
      stats: { unread: null },
      disconnect: null,
      loading: false,
      // 创建通知弹窗
      createVisible: false,
      // 详情弹窗
      detailVisible: false,
      detailLoading: false,
      detail: { id: null, title: '', type: '', publishedAt: '', content: '' },
    }
  },
  computed: {
    totalPages() {
      return Math.max(1, Math.ceil(this.page.total / this.page.pageSize))
    }
  },
  created() {
    this.fetchAll()
    this.initStream()
  },
  beforeUnmount() {
    if (this.disconnect) this.disconnect()
  },
  methods: {
    async fetchAll() {
      await Promise.all([this.fetchList(), this.fetchStats()])
    },
    async fetchList() {
      this.loading = true
      try {
        const typeMap = { all: '', mine: 'mention', system: 'system', company: 'company', product: 'product' }
        const type = typeMap[this.activeTab] || ''
        const { pageNum, pageSize } = this.page
        // 仅使用 read_status：READ -> 1，UNREAD -> 0
        let readStatusParam = undefined
        if (this.query.status === 'READ') readStatusParam = 1
        else if (this.query.status === 'UNREAD') readStatusParam = 0
        const params = {
          pageNum,
          pageSize,
          noticeTitle: this.query.keyword || undefined,
          noticeType: type || undefined,
          orderBy: 'publishTime',
          orderDirection: 'desc',
        }
        const res = await getUserNotices(params)
        const payload = res?.data
        // 兼容多种分页返回：
        // 1) { data: { records: [], total } }
        // 2) { records: [], total }
        // 3) { data: [] }
        let recs = []
        let total = 0
        if (payload?.data && (Array.isArray(payload.data) || typeof payload.data === 'object')) {
          const d = payload.data
          if (Array.isArray(d)) {
            recs = d
            total = payload.total ?? d.length
          } else {
            recs = d.records || d.list || []
            total = (typeof d.total === 'number' ? d.total : (payload.total ?? (Array.isArray(recs) ? recs.length : 0)))
          }
        } else {
          recs = payload?.records || payload?.list || []
          total = payload?.total ?? (Array.isArray(recs) ? recs.length : 0)
        }
        let mapped = Array.isArray(recs) ? recs.map(this.mapNotice) : []
        // 前端按需过滤已读/未读（因为后端查询 DTO 暂无该筛选）
        if (readStatusParam !== undefined) {
          mapped = mapped.filter(r => (readStatusParam === 1 ? r.read_status === 1 : r.read_status === 0))
        }
        this.list = mapped
        this.page.total = Number(total) || this.list.length
      } finally {
        this.loading = false
      }
    },
    // 将后端字段映射为前端统一字段（优先 readStatus，兼容 read_status）
    mapNotice(item) {
      const noticeId = item.noticeId ?? item.notice_id ?? item.messageId ?? null
      const userNoticeId = item.userNoticeId ?? item.user_notice_id ?? null
      const id = item.id ?? noticeId ?? userNoticeId
      const title = item.title ?? item.noticeTitle ?? item.messageTitle ?? item.name
      const type = item.type ?? item.noticeType ?? item.messageType
      const created = item.publishedAt ?? item.publishTime ?? item.createTime ?? item.gmtCreate
      const rawPref = item.readStatus
      const rawAlt = item.read_status
      const rawStatus = item.status
      let isRead = false
      if (rawPref !== undefined) {
        // readStatus 可能是 'READ'/'UNREAD' 或 1/0 或 true/false
        if (rawPref === 'READ' || rawPref === 'read' || rawPref === true || rawPref === 1 || rawPref === '1') isRead = true
        else if (rawPref === 'UNREAD' || rawPref === 'unread' || rawPref === false || rawPref === 0 || rawPref === '0') isRead = false
      } else if (rawAlt !== undefined) {
        isRead = (rawAlt === 1 || rawAlt === '1' || rawAlt === true)
      } else if (rawStatus !== undefined) {
        // 兼容后端用 status 表达已读：1=已读，0=未读
        isRead = (rawStatus === 1 || rawStatus === '1' || rawStatus === true || rawStatus === 'READ')
      }
      const readStatus = isRead ? 'READ' : 'UNREAD'
      const read_status = isRead ? 1 : 0
      return { id, noticeId, userNoticeId, title, type, publishedAt: created, readStatus, read_status }
    },
    // 统一的标记已读：尝试不同 ID 以适配后端可能的路径语义
    async tryMarkAsRead(row) {
      const candidates = [row.userNoticeId, row.user_notice_id, row.id, row.noticeId].filter(v => v !== undefined && v !== null)
      for (const cid of candidates) {
        try {
          await markAsRead(cid)
          row.readStatus = 'READ'
          row.read_status = 1
          this.fetchStats()
          return true
        } catch (_) { /* try next id */ }
      }
      return false
    },
    async markRead(row) {
      try {
        await this.tryMarkAsRead(row)
      } catch (_) {}
    },
    async viewDetail(row) {
      // 打开弹窗并预填基础信息
      this.detailVisible = true
      this.detailLoading = true
      this.detail = {
        id: row.id,
        title: row.title,
        type: row.type,
        publishedAt: row.publishedAt || row.createTime,
        content: ''
      }
      try {
        const res = await getNoticeDetail(row.id)
        const payload = res?.data
        const data = payload?.data || payload || {}
        const title = data.title ?? data.noticeTitle ?? data.messageTitle ?? row.title
        const type = data.type ?? data.noticeType ?? data.messageType ?? row.type
        const publishedAt = data.publishedAt ?? data.publishTime ?? data.createTime ?? data.gmtCreate ?? row.publishedAt
        const content = data.content ?? data.noticeContent ?? data.messageContent ?? data.body ?? data.text ?? ''
        this.detail = { id: row.id, title, type, publishedAt, content }
      } catch (_) {
        this.detail = { ...this.detail, content: '<div style="color:#f56c6c">内容加载失败</div>' }
      } finally {
        this.detailLoading = false
      }
      // 已读判断统一：read_status 或 readStatus 任一表明已读即不再请求
      const alreadyRead = (row.read_status === 1 || row.read_status === '1' || row.readStatus === 'READ' || row.readStatus === true || row.readStatus === 1 || row.readStatus === '1')
      if (!alreadyRead) {
        try {
          await this.tryMarkAsRead(row)
        } catch (_) {}
      }
    },
    async fetchStats() {
      try {
        const res = await getNoticeStats()
        const payload = res?.data
        const unread = payload?.data?.unread ?? payload?.unread
        if (typeof unread === 'number') this.stats.unread = unread
      } catch (_) { /* ignore */ }
    },
    onSearch() {
      this.page.pageNum = 1
      this.fetchList()
    },
    onReset() {
      this.query.keyword = ''
      this.query.status = ''
      this.page.pageNum = 1
      this.fetchList()
    },
    switchTab(tab) {
      if (this.activeTab === tab) return
      this.activeTab = tab
      this.page.pageNum = 1
      this.fetchList()
    },
    prevPage() { if (this.page.pageNum > 1) { this.page.pageNum--; this.fetchList() } },
    nextPage() { if (this.page.pageNum < this.totalPages) { this.page.pageNum++; this.fetchList() } },
    goToPage(p) { if (p!==this.page.pageNum) { this.page.pageNum = p; this.fetchList() } },
    onSizeChange() { this.page.pageNum = 1; this.fetchList() },
    formatTime(t) {
      if (!t) return '-'
      try {
        const d = new Date(t)
        const pad = (n) => (n<10?'0':'') + n
        return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
      } catch { return t }
    },
    // duplicate markRead removed; use the unified implementation above
    // async markRead(row) {
    //   try {
    //     await markAsRead(row.id)
    //     row.readStatus = 'READ'
    //     this.fetchStats()
    //   } catch (_) {}
    // },
    async remove(row) {
      try {
        await deleteNotice(row.id)
        // 从当前列表移除并尝试补位
        this.list = this.list.filter(i => i.id !== row.id)
        this.page.total = Math.max(0, this.page.total - 1)
        if (this.list.length === 0 && this.page.pageNum > 1) {
          this.page.pageNum -= 1
        }
        this.fetchList()
        this.fetchStats()
      } catch (_) {}
    },
    // duplicate viewDetail block removed to avoid nested method definitions

    closeDetail() { this.detailVisible = false },
    initStream() {
      try {
        this.disconnect = connectNoticeStream({
          onOpen: () => {},
          onMessage: (msg) => {
            // 后端可推送 { type: 'NEW_NOTICE' | 'UNREAD_COUNT', data: {...} }
            if (msg && typeof msg === 'object') {
              if (msg.type === 'UNREAD_COUNT') {
                if (typeof msg.data?.unread === 'number') this.stats.unread = msg.data.unread
              } else if (msg.type === 'NEW_NOTICE' || msg.type === 'NOTICE_CREATED' || msg.type === 'NOTICE_UPDATED') {
                this.fetchList()
                this.fetchStats()
              }
            } else {
              // 简单处理：有消息就刷新
              this.fetchList(); this.fetchStats()
            }
          },
          onError: () => {},
          onClose: () => {},
        });
      } catch (_) {}
    },
    // 创建通知相关方法
    showCreateForm() {
      this.createVisible = true;
    },
    closeCreateForm() {
      this.createVisible = false;
    },
    onCreateSuccess() {
      this.closeCreateForm();
      // 刷新列表和统计
      this.fetchAll();
      // 显示成功消息
      if (this.$message && this.$message.success) {
        this.$message.success('通知创建成功');
      }
    },
  }
}
</script>

<style scoped>
.message-notifications { padding: 20px; background-color: #f5f7fa; }
.controls-section { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 16px; padding: 20px; background: #fff; border-radius: 8px; margin-bottom: 16px; align-items: center; }
.filters { display: flex; gap: 16px; align-items: center; }
.filter-item { display: flex; gap: 8px; align-items: center; }
.filter-item input, .filter-item select { padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; width: 180px; }
.actions { display: flex; gap: 10px; align-items: center; }
.btn-primary { background: #409eff; color: #fff; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; }
.btn-secondary { background: #fff; color: #606266; border: 1px solid #dcdfe6; padding: 8px 16px; border-radius: 4px; cursor: pointer; }
.btn-success { background: #67c23a; color: #fff; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; }
.btn-danger { background: #f56c6c; color: #fff; border: 1px solid #f56c6c; padding: 6px 10px; border-radius: 4px; cursor: pointer; }
.btn-xs { font-size: 12px; padding: 4px 8px; margin-right: 6px; }
.unread-badge { color: #409eff; }
.tabs { display: flex; gap: 12px; margin-bottom: 12px; }
.tab { background: #fff; border: 1px solid #e5e7eb; padding: 8px 14px; border-radius: 6px; cursor: pointer; }
.tab.active { background: #409eff; color: #fff; border-color: #409eff; }
.table-section { background: #fff; border-radius: 8px; padding: 0 0 10px; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; border-bottom: 1px solid #ebeef5; text-align: left; }
th { background: #f8f9fa; }
.link-style { color: #409eff; cursor: pointer; }
.status-read { color: #2eaa3b; }
.status-unread { color: #f44336; }
.pagination { display: flex; gap: 8px; align-items: center; margin-top: 12px; }
.pagination button { padding: 6px 12px; border: 1px solid #dcdfe6; background: #fff; border-radius: 4px; cursor: pointer; }
.pagination button.active { background: #409eff; color: #fff; border-color: #409eff; }
.pagination select { padding: 6px; border: 1px solid #dcdfe6; border-radius: 4px; }

/* 详情弹窗样式 */
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.45); display: flex; align-items: center; justify-content: center; z-index: 2000; padding: 20px; }
.modal { width: min(820px, 92vw); max-height: 82vh; background: #fff; border-radius: 12px; overflow: hidden; box-shadow: 0 18px 40px rgba(0,0,0,0.22); display: flex; flex-direction: column; }
.modal-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; border-bottom: 1px solid #ebeef5; font-weight: 600; font-size: 16px; }
.modal-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: calc(100% - 36px); }
.modal-close { border: none; background: transparent; font-size: 22px; cursor: pointer; color: #909399; line-height: 1; }
.modal-close:hover { color: #606266; }
.modal-body { padding: 16px; overflow: auto; }
.modal-footer { padding: 12px 16px; border-top: 1px solid #ebeef5; display: flex; justify-content: flex-end; gap: 8px; }
.meta { color: #909399; font-size: 13px; display: flex; gap: 16px; margin-bottom: 10px; }
.loading { text-align: center; color: #909399; padding: 28px 0; }
.detail-content { color: #303133; line-height: 1.7; }
.detail-content h1, .detail-content h2, .detail-content h3 { margin: 12px 0 8px; }
.detail-content p { margin: 8px 0; }
.detail-content ul { margin: 8px 0 8px 18px; }
.detail-content img { max-width: 100%; height: auto; display: block; margin: 8px 0; }
</style>


